package com.hissy.cn.keyvalue;

import java.util.function.Function;

import com.alibaba.fastjson.JSON;

import com.hissy.cn.redis.JedisClientFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Response;

/**
 * Created by zhangyanfei on 2019/1/28.
 * redis  get set
 * 优化
 * 可以统一redis的存储目录
 *
 * 方法封装
 * @author zhangyanfei
 * @date 2019/01/28
 */
public class KeyValueService {

    /**
     *
     * @param db
     * @param func
     * @param <T>
     * @return
     */
    private <T> T execute(int db, Function<Pipeline,Response<T>> func){
        try(Jedis jedis= JedisClientFactory.getInstance().getDefaultJedisClient()){
            Pipeline pipeline=jedis.pipelined();
            pipeline.select(db);
            Response<T> response=func.apply(pipeline);
            pipeline.sync();
            return response.get();
        }
    }

    /**
     * Function<Pipeline, Response<T>>  == interface
     * @param db
     * @param func
     * @param key
     * @param seconds
     * @param <T>
     * @return
     */
    private <T> T execute(int db,Function<Pipeline, Response<T>> func,String key,int seconds){
        try (Jedis jedis = JedisClientFactory.getInstance().getDefaultJedisClient()) {
            Pipeline pipeline = jedis.pipelined();
            pipeline.select(db);
            Response<T> response = func.apply(pipeline);
            pipeline.expire(key,seconds);
            pipeline.sync();
            return response.get();
        }
    }

    /**
     * 固定key的格式
     * @param folder
     * @param key
     * @return
     */
    private String getRealKey(String folder, String key) {
        return folder != null ? folder + "/" + key : key;
    }

    /**
     * default DB
     * @return
     */
    private int getDefaultDB() {
        return 4;
    }

    public <T> T get(int db,String folder,String key,Class<T> clazz){
        String realKey=getRealKey(folder,key);
        return JSON.parseObject(execute(db, x->x.get(realKey)),clazz);
    }

    public <T> T get(String folder,String key,Class<T> clazz){
        String realKey=getRealKey(folder,key);
        return JSON.parseObject(execute(getDefaultDB(),x->x.get(realKey)),clazz);
    }

    public <T> T get(int db, String key,Class<T> clazz) {
        return JSON.parseObject(execute(db,x -> x.get(key)),clazz);
    }

    public <T> T get( String key,Class<T> clazz) {
        return JSON.parseObject(execute(getDefaultDB(),x -> x.get(key)),clazz);
    }

    public <T> void set(int db,String folder, String key, T value) {
        set(db,folder, key, JSON.toJSONString(value));
    }

    public <T> void set(String folder, String key, T value) {
        set(getDefaultDB(),folder, key, JSON.toJSONString(value));
    }

    public <T> void set(int db, String key, T value) {
        set(db, key, JSON.toJSONString(value));
    }

    public <T> void set( String key, T value) {
        set(getDefaultDB(), key, JSON.toJSONString(value));
    }


    public void set(int db,String folder, String key, String value) {
        String realKey = getRealKey(folder, key);
        execute(db,x ->x.set(realKey,value));
    }

    public void set(int db,String folder, String key, String value,int seconds) {
        String realKey = getRealKey(folder, key);
        execute(db,x ->x.set(realKey,value),realKey,seconds);
    }

    public void set(String folder, String key, String value) {
        String realKey = getRealKey(folder, key);
        execute(getDefaultDB(),x ->x.set(realKey,value));
    }

    public void set(String folder, String key, String value,int seconds) {
        String realKey = getRealKey(folder, key);
        execute(getDefaultDB(),x ->x.set(realKey,value),realKey,seconds);
    }

    public void set(int db, String key, String value) {
        execute(db,x ->x.set(key,value));
    }

    public void set(int db, String key, String value,int seconds) {
        execute(db,x ->x.set(key,value),key,seconds);
    }

    public void set(String key, String value) {
        execute(getDefaultDB(),x ->x.set(key,value));
    }

    public void set(String key, String value,int seconds) {
        execute(getDefaultDB(),x ->x.set(key,value),key,seconds);
    }

    public String setnx(int db,String folder, String key,String value,int expireTime) {
        String realKey = getRealKey(folder, key);
        return execute(db,x->x.set(realKey,value,"NX","PX", expireTime));
    }

}
